#include"Utility.hpp"

#include"../LibDGGSKernel/IDGGSKernel.hpp"
#include"../LibDGGSBase/MathDefine.hpp"
#include"../LibDGGSFeature/DGGSFeatureClass.hpp"
#include"../LibDGGSFeature/DGGSFeatureLayer.hpp"
#include"../LibDGGSFeature/DGGSFeature.hpp"
#include"../LibDGGSFeature/DGGSGeometry.hpp"
#include"../LibDGGSFeature/DGGSPoint.hpp"
#include"../LibDGGSFeature/DGGSPolyLine.hpp"
#include"../LibDGGSFeature/DGGSPolygon.hpp"

#include "gdal/ogrsf_frmts.h"
#include "gdal/ogr_geometry.h"
#include "gdal/gdal_priv.h"
#include "gdal/gdal_alg.h"

#include <vector>
#include <queue>
#include <iostream>

using namespace NNU::DGGS;
using namespace NNU::DGGS::Feature;
using namespace NNU::DGGS::Kernel;

/*
 * 获取、设置DGGS的几何对象的Codes
 * */

/// <summary>
///DGGS的点几何转为经纬度坐标组
/// <summary>
bool getCoordFromDGGS(DGGSPoint *dggsPoint, GeoCoord &coord, DGGSGridType gridType);
/// <summary>
///DGGS的线几何转为经纬度坐标组
/// <summary>
bool getCoordFromDGGS(DGGSPolyLine *dggsLines, GeoCoord *&coords, int &coordNum, DGGSGridType gridType);
/// <summary>
///DGGS的几何转为经纬度坐标组
bool getCoordFromDGGS(DGGSPolygon *dggsPolygon, GeoCoord *&coords, int &coordNum, DGGSGridType gridType);
/// <summary>
///DGGS的feature转为经纬度坐标组
/// <summary>
bool getDataFromDGGS(DGGSFeature* dggsFeature, int &fId, GeoCoord *&coords, int &coordNum);

/// <summary>
///经纬度坐标点转为DGGS的几何
/// <summary>
bool getDGGSFromCoord(GeoCoord coord, DGGSPoint *&dggsPoint, int level, DGGSGridType gridType, DGGSElementType elementType);
/// <summary>
///经纬度坐标组转线段几何的包含检测
/// <summary>
bool isContain(DGGSElementCode code, const std::vector<DGGSElementCode>& results);
/// <summary>
///经纬度坐标组转线段几何的格网增加
/// <summary>
void updateGrids(GeoCoord startPoint, GeoCoord endPoint, DGGSElementCode &currentCode, std::vector<DGGSElementCode> &results, int level, DGGSGridType gridType, DGGSElementType elementType);
/// <summary>
///经纬度坐标组转线段几何
/// <summary>
bool singleLine2Grid(GeoCoord startPoint, GeoCoord endPoint, DGGSElementCode*&codes, int &codeNum, int level, DGGSGridType gridType, DGGSElementType elementType);
/// <summary>
///经纬度坐标组转多段线几何
/// <summary>
bool getDGGSFromCoord(GeoCoord *coords, int coordNum, DGGSPolyLine *&dggsLines, int level, DGGSGridType gridType, DGGSElementType elementType);
/// <summary>
///经纬度坐标组转面几何的包含检测
/// <summary>
bool markCode(std::vector< long long int> &flag, DGGSElementCode code,int level,DGGSGridType gridType,DGGSElementType elementType) ;
/// <summary>
///经纬度坐标组转面几何
/// <summary>
bool getDGGSFromCoord(GeoCoord *coords, int coordNum, DGGSPolygon *&dggsPolygons, int level, DGGSGridType gridType, DGGSElementType elementType) ;
/// <summary>
///经纬度坐标组转DGGS的feature
/// <summary>
bool getDGGSFromCoord(int fId, GeoCoord *coords, int coordNum, DGGSFeature* &dggsFeature, int level, DGGSGridType gridType, DGGSElementType elementType, DGGSGeometryType geoType);

/*
 * 获取、设置OGR几何对象的经纬度坐标
 * */

/// <summary>
///点矢量转为经纬度坐标
/// <summary>
bool getCoordFromOGR(OGRPoint* ogrPoint, GeoCoord &coord);
/// <summary>
//线矢量转为经纬度坐标
/// <summary>
bool getCoordFromOGR(OGRLineString* ogrLine, GeoCoord *&coords, int &coordNum);
/// <summary>
///面矢量转为经纬度坐标
/// <summary>
bool getCoordFromOGR(OGRPolygon* ogrPolygon, GeoCoord *&coords, int &coordNum);
/// <summary>
///feature矢量转为经纬度坐标
/// <summary>
bool getDataFromOGR(OGRFeature* &ogrFeature, int &fId, GeoCoord *&coords, int &coordNum, OGRwkbGeometryType geomType);
/// <summary>
///经纬度转为点矢量
/// <summary>
bool getOGRFromCoord(GeoCoord coord, OGRPoint &ogrPoint);
/// <summary>
///经纬度转为线矢量
/// <summary>
bool getOGRFromCoord(GeoCoord *coords, int coordNum, OGRLineString &ogrLine);
/// <summary>
///经纬度转为面矢量
/// <summary>
bool getOGRFromCoord(GeoCoord *coords, int coordNum, OGRPolygon &ogrPolygon);
/// <summary>
///经纬度转为矢量feature
/// <summary>
bool getOGRFromCoord(int fId, GeoCoord *coords, int coordNum, OGRFeature* &ogrFeature, OGRwkbGeometryType geomType);

/*
 * 	实现OGR的feature与DGGS的Feature的相互转化
 * */

/// <summary>
/// OGR的feature转DGGS的Feature
/// </summary>
bool OGRFeature2DGGSFeature(OGRFeature *&ogrFeature, DGGSFeature *&dggsFeature);

/// <summary>
/// DGGS的Feature转OGR的feature
/// </summary>
bool DGGSFeature2OGRFeature(DGGSFeature *dggsFeature, OGRFeature *&ogrFeature);

/*
 * 	实现OGR的layer与DGGS的layer的相互转化
 * */

/// <summary>
/// DGGS的Feature图层转OGR的feature图层
/// </summary>
bool DGGSLayer2OGRLayer(DGGSFeatureLayer *dggsLayer, OGRLayer *&ogrLayer);

/// <summary>
/// OGR的feature图层转DGGS的Feature图层
/// </summary>
bool OGRLayer2DGGSLayer(OGRLayer *ogrLayer, DGGSFeatureLayer *&dggsLayer);


bool OGRFile2DGGSFile(const char* ogrFileName,const char* dggsFileName,int level,DGGSGridType gridType,DGGSElementType elementType)
{
    //读取源文件
    GDALAllRegister();
    auto srcDS = (GDALDataset*) GDALOpenEx(ogrFileName, GDAL_OF_VECTOR, nullptr, nullptr, nullptr);
    OGRLayer *ogrLayer = srcDS->GetLayer(0);
    auto ogrGeoType=ogrLayer->GetGeomType();

    //ogrLayer转dggsLayer

    DGGSGeometryType geometryType=DGGSGeometryType::ST_Unknown;
    switch(ogrGeoType) {
        case wkbPoint:
        case wkbPointM:
        case wkbPointZM:
            geometryType=DGGSGeometryType::ST_Point;
            break;
        case wkbLineString:
        case wkbLineStringM:
        case wkbLineStringZM:
            geometryType=DGGSGeometryType::ST_PolyLine;
            break;
        case wkbPolygon:
        case wkbPolygonM:
        case wkbPolygonZM:
            geometryType=DGGSGeometryType::ST_Polygon;
            break;
        default:
            break;
    }
    auto featureClass=new DGGSFeatureClass(level,geometryType,gridType,elementType);
    auto dggsLayer= new DGGSFeatureLayer(*featureClass);
    OGRLayer2DGGSLayer(ogrLayer, dggsLayer);
    GDALClose(srcDS);

    dggsLayer->saveToFile(dggsFileName);

    return true;
}

bool DGGSFile2OGRFile(const char* dggsFileName,const char* ogrFileName)
{
    //获取dggsLayer
    DGGSFeatureLayer dggsLayer;
    dggsLayer.loadFromFile(dggsFileName);
    DGGSGeometryType geometryType=dggsLayer.getFeatureClass()->getGeometryType();

    // 初始化GDAL
    OGRRegisterAll();
    const char* pszDriverName = "ESRI Shapefile";
    GDALDriver* poDriver = GetGDALDriverManager()->GetDriverByName(pszDriverName);

    // 创建一个新的数据源
    GDALDataset* pDataset = poDriver->Create(ogrFileName, 0, 0, 0, GDT_Unknown, nullptr);

    // 创建图层
    OGRSpatialReference spatialRef;
    spatialRef.SetWellKnownGeogCS("WGS84");
    OGRLayer* ogrLayer;
    switch (geometryType) {
        case DGGSGeometryType::ST_Point:
        {
            ogrLayer = pDataset->CreateLayer("new_shapefile", &spatialRef, wkbPoint, nullptr);
            DGGSLayer2OGRLayer(&dggsLayer, ogrLayer);
            break;
        }
        case DGGSGeometryType::ST_PolyLine:
        {
            ogrLayer = pDataset->CreateLayer("new_shapefile", &spatialRef, wkbLineString, nullptr);
            DGGSLayer2OGRLayer(&dggsLayer, ogrLayer);
            break;
        }
        case DGGSGeometryType::ST_Polygon:
        {
            ogrLayer = pDataset->CreateLayer("new_shapefile", &spatialRef, wkbPolygon, nullptr);
            DGGSLayer2OGRLayer(&dggsLayer, ogrLayer);
            break;
        }
        default:
            break;
    }

    GDALClose(pDataset);

    return true;
}


bool getCoordFromDGGS(DGGSPoint *dggsPoint, GeoCoord &coord, DGGSGridType gridType)
{
    DGGSElementCode *codes= nullptr;
    dggsPoint->getGridData(codes);
    IDGGSKernel * pKernel= CreateKernelObj(gridType);
    pKernel->decode(codes[0],coord);
    DestroyKernelObj(pKernel);
    delete[]codes;
    return true;
}

bool getCoordFromDGGS(DGGSPolyLine *dggsLines, GeoCoord *&coords, int &coordNum, DGGSGridType gridType)
{
    IDGGSKernel * pKernel= CreateKernelObj(gridType);

    //获取格网数量
    coordNum=dggsLines->getGridCount();
    coords=new GeoCoord[coordNum];

    //格网转为经纬度
    int coordId=0;
    DGGSElementCode *codes= nullptr;
    dggsLines->getGridData(codes);
    for(int i=0;i<coordNum;i++)
    {
        GeoCoord coord{};
        pKernel->decode(codes[i],coord);
        coords[coordId++]=coord;
    }
    delete[]codes;

    DestroyKernelObj(pKernel);
    return true;
}

bool getCoordFromDGGS(DGGSPolygon *dggsPolygon, GeoCoord *&coords, int &coordNum, DGGSGridType gridType)
{
    IDGGSKernel * pKernel= CreateKernelObj(gridType);

    //获取格网及其数量
    int codeNum=dggsPolygon->getGridCount();

    DGGSElementCode *codes= nullptr;
    dggsPolygon->getGridData(codes);
    std::vector<DGGSElementCode>boundCodes;

    //获取边界格网
    int level=0;

    for(int i=0;i<codeNum;i++)
    {
        if(i==0)
            level=codes[i].level;
        else if(level>codes[i].level)
            break;
        boundCodes.push_back(codes[i]);
    }
    delete[]codes;

    coordNum=(int)boundCodes.size();
    coords=new GeoCoord[coordNum];

    int coordId=0;

    for(int i=0;i<coordNum;i++)
    {
        GeoCoord coord{};
        pKernel->decode(boundCodes[i],coord);
        coords[coordId++]=coord;
    }

    DestroyKernelObj(pKernel);
    return true;
}

bool getDataFromDGGS(DGGSFeature* dggsFeature, int &fId, GeoCoord *&coords, int &coordNum)
{
    //获取FId
    fId=(int)dggsFeature[0].getFID();

    //获取几何
    DGGSGeometry *geometry=dggsFeature->getGeometry();
    DGGSGeometryType geomType=dggsFeature->getGeomType();
    DGGSGridType gridType=dggsFeature->getGridType();
    switch (geomType) {
        case ST_Point:
        {
            coordNum=1;
            coords=new GeoCoord[coordNum];
            getCoordFromDGGS((DGGSPoint*)geometry,coords[0],gridType);
            break;
        }

        case ST_PolyLine:
        {
            getCoordFromDGGS((DGGSPolyLine*)geometry,coords,coordNum,gridType);
            break;
        }

        case ST_Polygon:
        {
            getCoordFromDGGS((DGGSPolygon*)geometry,coords,coordNum,gridType);
            break;
        }
        default:
            break;
    }

    return true;
}

bool getDGGSFromCoord(GeoCoord coord, DGGSPoint *&dggsPoint, int level, DGGSGridType gridType, DGGSElementType elementType)
{
    IDGGSKernel*pKernel= CreateKernelObj(gridType);

    DGGSElementCode code;
    code.level=level;
    code.elementType=elementType;

    pKernel->encode(coord,code);
    dggsPoint=new DGGSPoint[1];
    dggsPoint->setGridCount(1);
    dggsPoint->setGridData(&code);

    DestroyKernelObj(pKernel);
    return true;
}

bool isContain(DGGSElementCode code, const std::vector<DGGSElementCode>& results)
{
    for(auto tempCode:results)
        if(code==tempCode)
            return true;
    return false;
}

void updateGrids(GeoCoord startPoint, GeoCoord endPoint, DGGSElementCode &currentCode, std::vector<DGGSElementCode> &results, int level, DGGSGridType gridType, DGGSElementType elementType)
{
    double differ= calculateDiffer(level);
    DGGSElementCode endCell;
    endCell.level=level;
    endCell.elementType=elementType;

    IDGGSKernel* pKernel= CreateKernelObj(gridType);
    pKernel->encode(endPoint, endCell);

    DGGSElementCodeIter* iter= nullptr;
    int elementNum=0;
    pKernel->query(DGGSTopoType::RelativeCells, currentCode, iter, elementNum);

    //获取最佳code
    DGGSElementCode minCode;
    double minAngle=M_PI;

    DGGSElementCodeIter* tempIter=iter;
    while (tempIter!= nullptr)
    {
        GeoCoord coord{};
        pKernel->decode(tempIter->code,coord);

        //判断是否为终点
        if(tempIter->code==endCell) {
            currentCode= endCell;
            break;
        }
        //判断是否为已有格元
        if(isContain(tempIter->code,results))
        {
            tempIter=tempIter->next;
            continue;
        }
        //跨界
        if((coord.lon<startPoint.lon-differ/2&&coord.lon<endPoint.lon-differ/2)||(coord.lon>startPoint.lon+differ/2&&coord.lon>endPoint.lon+differ/2))
        {
            tempIter=tempIter->next;
            continue;
        }

        //格子在矢量线上
        int vertexesNum;
        DGGSElementCodeIter *vertexesIter= nullptr;
        pKernel->query(DGGSTopoType::RelativeVertexes, tempIter->code,vertexesIter,vertexesNum);

        auto geoCoords=new GeoCoord[vertexesNum];
        bool b180=false;
        bool b_180=false;
        for(int num=0;num<vertexesNum;num++)
        {
            GeoCoord tempCoord{};
            pKernel->decode(vertexesIter[num].code, tempCoord);
            geoCoords[num]=tempCoord;
            if(fabs(-180.0-tempCoord.lon)<72.0)
                b_180=true;
            if(fabs(180.0-tempCoord.lon)<72.0)
                b180=true;
        }
        delete[]vertexesIter;

        if(b180&&b_180)
        {
            for(int i=0;i<vertexesNum;i++)
            {
                if(coord.lon>0)
                {
                    if(fabs(-180.0-geoCoords[i].lon)<differ*2)
                        geoCoords[i].lon+=360.0;
                }
                else if(coord.lon<0)
                {
                    if(fabs(180.0-geoCoords[i].lon)<differ*2)
                        geoCoords[i].lon-=360.0;
                }
            }
        }
        if (!Intersect(geoCoords,vertexesNum, startPoint, endPoint))
        {
            tempIter=tempIter->next;
            continue;
        }

        //找最近格子
        double curAngle=calAngle({startPoint.lon,startPoint.lat},{coord.lon,coord.lat},{endPoint.lon,endPoint.lat});
        if(curAngle<minAngle)
        {
            minCode=tempIter->code;
            minAngle=curAngle;
        }
        tempIter=tempIter->next;
    }

    delete[]iter;
    iter= nullptr;
    //如果矢量刚好和两个格子的分界线重合
    if (minAngle == M_PI)
    {
        pKernel->query(DGGSTopoType::RelativeCells, currentCode, iter, elementNum);
        tempIter=iter;
        while (tempIter!= nullptr)
        {
            GeoCoord tempCoord{};
            pKernel->decode(tempIter->code, tempCoord);

            //判断是否为已有格元
            if(isContain(tempIter->code,results))
            {
                tempIter=tempIter->next;
                continue;
            }

            //找最近格子
            double curAngle = calAngle({startPoint.lon,startPoint.lat},{tempCoord.lon,tempCoord.lat},{endPoint.lon,endPoint.lat});
            if (curAngle < minAngle)
            {
                minCode=tempIter->code;
                minAngle=curAngle;
            }
            tempIter=tempIter->next;
        }
    }

    if(!(currentCode==endCell))
        currentCode=minCode;

    if(iter!= nullptr)
        delete[]iter;
    results.push_back(currentCode);
    DestroyKernelObj(pKernel);
}

bool singleLine2Grid(GeoCoord startPoint, GeoCoord endPoint, DGGSElementCode*&codes, int &codeNum, int level, DGGSGridType gridType, DGGSElementType elementType)
{
    std::vector<DGGSElementCode> lineGrid;
    IDGGSKernel*pKernel= CreateKernelObj(gridType);
    //首先标明线的起点和终点
    DGGSElementCode code;
    code.level = level;
    code.elementType=elementType;

    pKernel->encode(startPoint, code);
    DGGSElementCode startCell = code;
    pKernel->encode(endPoint, code);
    DGGSElementCode endCell = code;

    DGGSElementCode currentCell = startCell;
    lineGrid.push_back(currentCell);
    int count = 0;

    //通过计算角度得到最终需要的格子
    while (!(currentCell==endCell))
    {
        count++;
        updateGrids(startPoint, endPoint, currentCell, lineGrid, level,gridType,elementType);
    }

    DestroyKernelObj(pKernel);

    codeNum=(int)lineGrid.size();
    codes=new DGGSElementCode[codeNum];
    for(int i=0;i<codeNum;i++)
    {
        codes[i]=lineGrid[i];
    }
    return true;
}

bool getDGGSFromCoord(GeoCoord *coords, int coordNum, DGGSPolyLine *&dggsLines, int level, DGGSGridType gridType, DGGSElementType elementType)
{
    //获取所有格网
    std::vector<DGGSElementCode> stringLineGrid;
    for(int i=0;i< coordNum-1;i++)
    {
        GeoCoord startPoint=coords[i];
        GeoCoord endPoint=coords[i + 1];
        if(gridType!=DGGSGridType::DGGS_ISEA4H)
        {
            double differ= calculateDiffer(level);
            if(fabs(180-startPoint.lon)<differ/2)
                startPoint.lon-=differ/2;
            if(fabs(-180-startPoint.lon)<differ/2)
                startPoint.lon+=differ/2;
            if(fabs(180-endPoint.lon)<differ/2)
                endPoint.lon-=differ/2;
            if(fabs(-180-endPoint.lon)<differ/2)
                endPoint.lon+=differ/2;
        }

        DGGSElementCode*codes= nullptr;
        int codeNum=0;
        singleLine2Grid(startPoint, endPoint,codes,codeNum,level,gridType,elementType);
        for(int g=0;g<codeNum;g++)
            stringLineGrid.push_back(codes[g]);
        delete[]codes;
    }

    //设置DGGSlines
    int codeCount=(int)stringLineGrid.size();
    auto gridData=new DGGSElementCode[codeCount];

    for(int codeId=0;codeId<codeCount;codeId++)
        gridData[codeId]=stringLineGrid[codeId];

    dggsLines->setGridCount(codeCount);
    dggsLines->setGridData(gridData);
    delete[]gridData;

    return true;
}

bool markCode(std::vector< long long int> &flag, DGGSElementCode code,int level,DGGSGridType gridType,DGGSElementType elementType) {
    auto maxRow=(long long int)pow(2,level);
    long long int maxCol=0;
    switch (elementType) {
        case DGGSElementType::Edge:
            maxCol=eColMaxSize(level,gridType);
            break;
        case DGGSElementType::Vertex:
            maxCol=vColMaxSize(level,gridType);
            break;
        case DGGSElementType::Cell:
            maxCol=fColMaxSize(level,gridType);
            break;
        default:break;
    }

    long long int label=code.basePartition*maxRow*maxCol+code.row*maxCol+code.col;
    auto it = std::find(flag.begin(), flag.end(), label);
    if (it != flag.end())//找到
        return false;
    else
    {
        flag.push_back(label);
        return true;
    }
}

bool getDGGSFromCoord(GeoCoord *coords, int coordNum, DGGSPolygon *&dggsPolygons, int level, DGGSGridType gridType, DGGSElementType elementType) {
    //获取外环格网
    std::vector<DGGSElementCode> stringLineGrid;
    for (int i = 0; i < coordNum-1; i++) {
        GeoCoord startPoint = coords[i];
        GeoCoord endPoint = coords[i + 1];

        DGGSElementCode *codes = nullptr;
        int codeNum = 0;
        singleLine2Grid(startPoint, endPoint, codes, codeNum, level, gridType, elementType);
        for (int g = 0; g < codeNum; g++) {
            auto length=stringLineGrid.size();
            if (length==0||stringLineGrid[length-1] != codes[g])
                stringLineGrid.push_back(codes[g]);
        }
        delete[]codes;
    }

    //获取内部所有格网
    std::vector<DGGSElementCode> polygonCodes;
    std::queue<DGGSElementCode> element;
    std::vector<long long int> flag;
    for (int i = 0; i < stringLineGrid.size(); i++)
        element.push(stringLineGrid[i]);

    //用一个上层级的code标记多边形外环
    DGGSElementCode flagCode=element.front();
    flagCode.level-=1;

    IDGGSKernel*pKernel= CreateKernelObj(gridType);

    while(!element.empty()) {
        DGGSElementCode code;
        code = element.front();
        element.pop();
        polygonCodes.push_back(code);

        //防止标记影响正确结果
        if(polygonCodes.size()==stringLineGrid.size())
        {
            polygonCodes.push_back(flagCode);
        }

        markCode(flag, code,level,gridType,elementType);
        DGGSElementCodeIter *cellIter = nullptr;
        int cellsNum;
        pKernel->query(DGGSTopoType::RelativeCells, code, cellIter, cellsNum);

        for (int k = 0; k < cellsNum; k++) {
            GeoCoord coord{0, 0};
            pKernel->decode(cellIter[k].code, coord);
            if (!markCode(flag,cellIter[k].code,level,gridType,elementType))
                continue;
            if(isContain(cellIter[k].code,stringLineGrid))
                continue;
            if(isPointInPolygon(coords,coordNum, coord))
                element.push(cellIter[k].code);
        }
        delete[]cellIter;
    }

    DestroyKernelObj(pKernel);

    int codeNum=(int)polygonCodes.size();
    auto codeData=new DGGSElementCode[codeNum];

    for(int i=0;i<codeNum;i++)
        codeData[i]=polygonCodes[i];

    dggsPolygons->setGridCount(codeNum);
    dggsPolygons->setGridData(codeData);


    return true;
}

bool getDGGSFromCoord(int fId, GeoCoord *coords, int coordNum, DGGSFeature* &dggsFeature, int level, DGGSGridType gridType, DGGSElementType elementType, DGGSGeometryType geoType)
{
    switch (geoType) {
        case DGGSGeometryType::ST_Point:
        {
            auto point= new DGGSPoint();
            getDGGSFromCoord(coords[0], point, level, gridType, elementType);
            dggsFeature->setGeometry(point);
            break;
        }
        case ST_PolyLine:
        {
            auto lines= new DGGSPolyLine();
            getDGGSFromCoord(coords,coordNum, lines, level, gridType, elementType);
            dggsFeature->setGeometry(lines);
            break;
        }
        case ST_Polygon:
        {
            auto polygons= new DGGSPolygon();
            getDGGSFromCoord(coords,coordNum, polygons, level, gridType, elementType);
            dggsFeature->setGeometry(polygons);
            break;
        }
        default:
            break;
    }
    dggsFeature->setFID(fId);

    return true;
}

bool getCoordFromOGR(OGRPoint* ogrPoint, GeoCoord &coord)
{
    double lon = ogrPoint->getX();
    double lat = ogrPoint->getY();
    coord.lat = lat;
    coord.lon = lon;
    return true;
}

bool getCoordFromOGR(OGRLineString* ogrLine, GeoCoord *&coords, int &coordNum)
{
    coordNum=ogrLine->getNumPoints();
    coords=new GeoCoord[coordNum];
    for (int i = 0; i < coordNum; i++)
    {
        OGRPoint point;
        ogrLine->getPoint(i, &point);
        GeoCoord coord{};
        double lon = point.getX();
        double lat = point.getY();
        coord.lon = lon;
        coord.lat = lat;
        coords[i]=coord;
    }
    return true;
}

bool getCoordFromOGR(OGRPolygon* ogrPolygon, GeoCoord *&coords, int &coordNum)
{
    OGRLineString *poRing =ogrPolygon->getExteriorRing() ;
    coordNum= poRing->getNumPoints();
    coords=new GeoCoord[coordNum];

    for (int j = 0; j <coordNum; j++) {
        OGRPoint poPoint;
        poRing->getPoint(j, &poPoint);
        GeoCoord coord{};
        double lon = poPoint.getX();
        double lat = poPoint.getY();
        coord.lon = lon;
        coord.lat = lat;
        coords[j]=coord;

    }
    return true;
}

bool getDataFromOGR(OGRFeature* &ogrFeature, int &fId, GeoCoord *&coords, int &coordNum, OGRwkbGeometryType geomType)
{
    fId=(int)ogrFeature->GetFID();
    OGRGeometry *geometry = ogrFeature->GetGeometryRef();

    //OGRwkbGeometryType geomType = wkbFlatten(geometry->getGeometryType());
    switch (geomType) {
        case wkbPoint:
        case wkbPointZM:
        {
            coordNum=1;
            coords=new GeoCoord[1];
            getCoordFromOGR((OGRPoint*)geometry, coords[0]);
            break;}
        case wkbLineString:
        case wkbLineStringZM:
        {
            getCoordFromOGR((OGRLineString*)geometry, coords,coordNum);
            break;}
        case wkbPolygon:
        {

            getCoordFromOGR((OGRPolygon*)geometry, coords,coordNum);
            break;}
        default:
            break;
    }
    return true;
}

bool getOGRFromCoord(GeoCoord coord, OGRPoint &ogrPoint)
{
    ogrPoint.setX(coord.lon);
    ogrPoint.setY(coord.lat);

    return true;
}

bool getOGRFromCoord(GeoCoord *coords, int coordNum, OGRLineString &ogrLine)
{
    for (int j = 0; j <coordNum; ++j) {
        GeoCoord coord=coords[j];
        OGRPoint point;
        point.setX(coord.lon);
        point.setY(coord.lat);
        ogrLine.addPoint(&point);
    }
    return true;
}

bool getOGRFromCoord(GeoCoord *coords, int coordNum, OGRPolygon &ogrPolygon)
{
    OGRLinearRing linearRing;
    for (int j = 0; j <coordNum; ++j) {
        GeoCoord coord=coords[j];
        OGRPoint point;
        point.setX(coord.lon);
        point.setY(coord.lat);
        linearRing.addPoint(&point);
    }
    linearRing.closeRings();
    ogrPolygon.addRing(&linearRing);

    return true;
}

bool getOGRFromCoord(int fId, GeoCoord *coords, int coordNum, OGRFeature* &ogrFeature, OGRwkbGeometryType geomType)
{
    //设置FId
    ogrFeature->SetField("FID", fId);

    int boundCount=0;
    //设置几何
    switch (geomType) {
        case wkbPoint:
        {
            OGRPoint ogrPoint;
            boundCount=getOGRFromCoord(coords[0], ogrPoint);
            ogrFeature->SetGeometry(&ogrPoint);
            break;
        }
        case wkbLineString:
        {
            OGRLineString ogrLine;
            boundCount=getOGRFromCoord(coords, coordNum, ogrLine);
            ogrFeature->SetGeometry(&ogrLine);
            break;
        }
        case wkbPolygon:
        {
            OGRPolygon ogrPolygon;
            boundCount=getOGRFromCoord(coords, coordNum, ogrPolygon);
            ogrFeature->SetGeometry(&ogrPolygon);
            break;
        }

        default:
            break;
    }

    return boundCount;
}

bool OGRFeature2DGGSFeature(OGRFeature *&ogrFeature, DGGSFeature *&dggsFeature)
{
    int fId=0;
    GeoCoord *coords= nullptr;
    int coordNum=0;
    OGRwkbGeometryType geoType=ogrFeature->GetGeometryRef()->getGeometryType();
    getDataFromOGR(ogrFeature,fId,coords,coordNum, geoType);

    int level=dggsFeature->getLevel();
    DGGSGridType gridType=dggsFeature->getGridType();
    DGGSElementType elementType=dggsFeature->getElementType();

    DGGSGeometryType dggsGeometryType=DGGSGeometryType::ST_Unknown;
    switch (geoType) {
        case wkbPoint:
        case wkbPointM:
        case wkbPointZM:
            dggsGeometryType=DGGSGeometryType::ST_Point;
            break;
        case wkbLineString:
        case wkbLineStringM:
        case wkbLineStringZM:
            dggsGeometryType=DGGSGeometryType::ST_PolyLine;
            break;
        case wkbPolygon:
        case wkbPolygonM:
        case wkbPolygonZM:
            dggsGeometryType=DGGSGeometryType::ST_Polygon;
            break;
        default:
            break;
    }

    getDGGSFromCoord(fId,coords,coordNum,dggsFeature,level,gridType,elementType,dggsGeometryType);
    delete[]coords;
    return true;
}

bool DGGSFeature2OGRFeature(DGGSFeature *dggsFeature, OGRFeature *&ogrFeature)
{
    int fId=0;
    GeoCoord *coords= nullptr;
    int coordNum=0;
    getDataFromDGGS( dggsFeature,fId, coords,coordNum);
    OGRwkbGeometryType ogrGeomType=OGRwkbGeometryType::wkbUnknown;

    DGGSGeometryType dggsGeomType=dggsFeature->getGeomType();
    if(dggsGeomType==DGGSGeometryType::ST_Point)
        ogrGeomType=OGRwkbGeometryType::wkbPoint;
    else if(dggsGeomType==DGGSGeometryType::ST_PolyLine)
        ogrGeomType=OGRwkbGeometryType::wkbLineString;
    else if(dggsGeomType==DGGSGeometryType::ST_Polygon)
        ogrGeomType=OGRwkbGeometryType::wkbPolygon;

    getOGRFromCoord( fId,coords, coordNum,ogrFeature,ogrGeomType);
    return false;
}

bool DGGSLayer2OGRLayer(DGGSFeatureLayer *dggsLayer, OGRLayer *&ogrLayer)
{
    //添加字段
    OGRFieldDefn oFieldName("FID", OFTInteger64);
    oFieldName.SetWidth(32);
    ogrLayer->CreateField(&oFieldName) ;

    //feature转化
    int featureNum=dggsLayer->getFeatureCount();
    for(int i=0;i<featureNum;i++)
    {
        DGGSFeature*dggsFeature=dggsLayer->getFeature(i);
        OGRFeature* ogrFeature = OGRFeature::CreateFeature(ogrLayer->GetLayerDefn());
        DGGSFeature2OGRFeature(dggsFeature, ogrFeature);

        ogrLayer->CreateFeature(ogrFeature);
    }

    return true;

}

bool OGRLayer2DGGSLayer(OGRLayer *ogrLayer, DGGSFeatureLayer *&dggsLayer)
{
    OGRFeature* ogrFeature = nullptr;
    while ((ogrFeature = ogrLayer->GetNextFeature()) != nullptr) {

        DGGSFeature*dggsFeature=dggsLayer->getFeatureClass()->createFeature();
        OGRFeature2DGGSFeature(ogrFeature, dggsFeature);
        dggsLayer->addFeature(dggsFeature);
        OGRFeature::DestroyFeature(ogrFeature);
    }
    return true;
}












